package org.semanticflash.rdf
{
	
	
	import com.adobe.crypto.SHA1;
	import com.bigflexlib.ds.DataStructureEvent;
	import com.bigflexlib.ds.container.ContainerDiff;
	import com.bigflexlib.ds.container.zet.IOSet;
	
	import org.semanticflash.rdf.graph.RDFIndexedGraph;
	import org.semanticflash.rdf.graph.RDFManualSource;
	import org.semanticflash.rdf.graph.source.RDFRemoteSource;
	import org.semanticflash.rdf.triple.RDFTriple;
	import org.semanticflash.rdf.values.IRI;
	import org.semanticflash.rdf.values.RDFPlainLiteral;
	import org.semanticflash.rdf.values.RDFValue;
	import org.semanticflash.rdf.vocab.Vfoaf;
	import org.semanticflash.rdf.vocab.Vowl;

	
	
	
	/**
	 * 
	 * This is a dev time class where we put some things together
	 * to power a simple linked data browser
	 * 
	 * graph, reasoner, scutter, uimanager, etc
	 * 
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */	
	public class RDFService
	{
		
		
		private var _graph:RDFIndexedGraph;
		

		
		public function get graph( ):RDFIndexedGraph
		{
			return _graph;
		}
		




		private var manualSource:RDFManualSource = new RDFManualSource( );		
		
		
		
		
		public function RDFService( )
		{
			
			
			_graph = new RDFIndexedGraph( );
			
			_graph.sources.add( manualSource );		
			
			
			
			
//			t( null, Vfoaf._mbox, null, foaf_mbox );
//			t( null, Vfoaf._mbox_sha1sum, null, foaf_mbox_sha1sum );
//			t( null, Vowl._sameAs, null, owl_sameAs );
			
			
		}
		
		
		
		
		private function foaf_mbox( t:RDFTriple ):void
		{
			
			
			var str:String;
			if ( t.o is IRI ) // mailto: iri
			{
				str = ( t.o as IRI ).stringForm;
			}
			else // literal... semantic error
			{
				return;
			}
			
			var sha1:String = SHA1.hash( str );
			var t2:RDFTriple = RDFTriple.instance( t.s, Vfoaf._mbox_sha1sum, RDFPlainLiteral.instance( sha1 ) );
			manualSource.editableTriples.add( t2 );
			
		}
		
		private function foaf_mbox_sha1sum( t:RDFTriple ):void
		{
			
			
			var mask:RDFTriple = RDFTriple.instance( null, Vfoaf._mbox_sha1sum, t.o );
			var triples:IOSet = _graph.getTriples( mask );
			triples.walk( function( e:*, m:int ):void {

					_graph.redirectionContext.eq( e.s as IRI, t.s as IRI );
					
				} );
			
		}
		
		private function owl_sameAs( t:RDFTriple ):void
		{
			var eq:Boolean = _graph.redirectionContext.eq( t.s as IRI, t.o as IRI );
		}

		
		

		private function t( s:RDFValue, p:IRI, o:RDFValue, handler:Function ):void
		{
			
			var f:Function = function( event:DataStructureEvent ):void {
					var diff:ContainerDiff = event.diff as ContainerDiff;
					diff.addedElements.walk( function ( e:*, m:int ):void{
						handler.call( null, e as RDFTriple );
					} );
				}
			_graph.getTriples( RDFTriple.instance( s, p, o ) ).addEventListener( DataStructureEvent.CHANGE, f );
		}


		


		
		
		/**
		 * 
		 * A quick method to load an rdf doc into the graph
		 * 
		 * @param iri
		 * 
		 */		
		public function load( iri:IRI ):void
		{

			var source:RDFRemoteSource = RDFRemoteSource.forIRI( iri );
			if ( source == null ) // not dereferencable
			{
				return;			
			}
			
			
			if ( _graph.sources.contains( source ) )
				return;
			
			// add to the graph ( this is idempotent )
			_graph.sources.add( source );
			
			// and start loading ( this is idempotent ) NO... UNTIL WE RESOLVE BNODE CONSOLIDATION
			source.load( );

		}
		
		
		
		
		
		
		
		
		
		
		

		
		
		/////////////////////////////////////////////////////////////////
		//////////////////////////// factory ////////////////////////////
		/////////////////////////////////////////////////////////////////
		
		
		private static var instance:RDFService;
		
		
		/**
		 * 
		 * We provide a singleton during dev time to ease the building 
		 * of prototypes.
		 * We should find an alternative
		 * ( attach to a node in the displaylist sounds like a nice alternative )
		 * 
		 * RDFService.forDisplayObject( dobj )...
		 * 
		 * Traverses up the hierarchy until it hits an object with a registered service
		 * 
		 * @return 
		 * 
		 */		
		public static function get i( ):RDFService
		{
			if ( !instance )
				instance = new RDFService( );
				
			return instance;			
		
		}
		
		
		
	}


}